.TITLE LTDRV .IDENT /05/ ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 05 ; ; DAVID R. CROWE ; ; PREVIOUSLY MODIFIED BY: ; ; DAVID H. CHAN ; HELEN GORDON ; PATRICIA C. LEE ; ; ; MODIFIED BY: ; ; R. E. CALDWELL 21-AUG-79 ; ; RC010 -- FIX BUG IN CANCEL I/O ; AND USE CORRECT FORM OF GTPKT$. ; ; PARALLEL COMMUNICATION LINK (PCL) TRANSMITTER DRIVER FOR RSX-11M-PLUS. ; ; MACRO LIBRARY CALLS ; .MCALL PKTDF$,TCBDF$,UCBDF$ PKTDF$ ;DEFINE I/O PACKET OFFSETS TCBDF$ ;DEFINE TASK CONTROL BLOCK OFFSETS. UCBDF$ ;DEFINE UCB OFFSETS ;+ ; STATE SETTINGS FOR 'STC' FUNCTION ;- SS.MAS = 1 ;MASTER STATE ;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED ;SS.SEC = 2 ;SECONDARY STATE SS.NEU = 4 ;NEUTRAL STATE ;+ ; MODE SETTINGS FOR 'STC' FUNCTION ;- MS.AUT = 20 ;AUTO ADDRESS MS.ADS = 40 ;ADDRESS SILO ;+ ; CHARACTERISTIC WORD USAGE. ; U.CW2 IS USED BY THE HANDLER AS FOLLOWS: ; BITS 7-0 CONTAIN NUMBER OF RETRIES TO BE PERFORMED AFTER CURRENT ; TRY IF NECESSARY. ;- ;+ ; HANDLER UCB WORK AREA OFFSET DEFINITIONS. ;- U.EFN = U.CNT+2 ;'NOWMST' EVENT FLAG NUMBER U.TCB = U.EFN+2 ;TCB ADDRESS OF EVENT FLAG REQUESTOR U.BUF1 = U.TCB+2 ;RELOCATION BIAS FOR RETURN REG. BUFFER ;+ ; THE HARDWARE REGISTERS ARE DEFINED RELATIVE TO THE TCR, WHOSE ; ADDRESS IS FOUND IN THE S.CSR FIELD OF THE SCB AT RUN TIME. ;- TCR = 0 ;TRANSMITTER COMMAND REGISTER. TSR = 2 ;TRANSMITTER STATUS REGISTER. TSDB = 4 ;TRANSMITTER SOURCE DATA BUFFER. TSBC = 6 ;TRANSMITTER SOURCE BYTE COUNT. TSBA = 10 ;TRANSMITTER SOURCE BUS ADDRESS. TMMR = 12 ;TRANSMITTER MASTER/MAINTENANCE REG. TSCRC = 14 ;TRANSMITTER SOURCE CRC ;+ ; TRANSMITTER COMMAND REGISTER (TCR). ;- RIB = 100000 ;RETRY IF BUSY (R/W). TXNPR = 40000 ;TRANSMITTER NPR (R/W). SNDWD = 20000 ;SEND WORD (R/W). DC04 = 10000 ;DESTINATION CODE BITS (R/W). DC03 = 4000 ; " DC02 = 2000 ; " DC01 = 1000 ; " DC00 = 400 ; " RDSILO = 200 ;READ SILO (R/W). IE = 100 ;INTERRUPT ENABLE (R/W). A17 = 40 ;EXTENDED ADDRESS BITS (R/W). A16 = 20 ; " DTORDY = 10 ;DATA OUTPUT READY (RO). INHADI = 4 ;INHIBIT ADDRESS INCREMENT (R/W). BDINIT = 2 ;BOARD INITIALIZE (WO). STTXM = 1 ;START TRANSMISSION (R/W). DC = DC04!DC03!DC02!DC01!DC00 ;UNION OF DESTINATION CODE BITS. ;+ ; TRANSMITTER STATUS REGISTER (TSR). ;- ERR = 100000 ;ERROR (RO). NEXLOC = 40000 ;NONEXISTENT LOCATION (RO). MEMOFL = 20000 ;MEMORY OVERFLOW (R/W). TXMERR = 10000 ;TRANSMISSION ERROR (R/W). MSTDWN = 4000 ;MASTER DOWN (R/W). TIMOUT = 2000 ;TIME OUT (R/W). OVERUN = 1000 ;OVERRUN (R/W). DTIRDY = 400 ;DATA INPUT READY (RO). SUCTXF = 200 ;SUCCESSFUL TRANSFER (R/W). BUSY = 100 ;BUSY (RO). SORE = 40 ;SOFTWARE REJECT (R/W). TDMBSY = 20 ;TDM BUS BUSY (R/W). RSPB1 = 10 ;RESPONSE B1 (RO). RSPB0 = 4 ;RESPONSE B0 (RO). RSPA1 = 2 ;RESPONSE A1 (RO). RSPA0 = 1 ;RESPONSE A0 (RO). ;+ ; TRANSMITTER MASTER/MAINTENANCE REGISTER (TMMR). ;- ; LOW ORDER BYTE (TMMR+0). TXMAD4 = 20 ;TRANSMITTER ADDRESS BITS (R/W). TXMAD3 = 10 ; " TXMAD2 = 4 ; " TXMAD1 = 2 ; " TXMAD0 = 1 ; " ; HIGH ORDER BYTE (TMMR+1). AOPRDY = 200 ;ADDRESS OUTPUT READY (RO). AIPRDY = 100 ;ADDRESS INPUT READY (RO). CLRADR = 40 ;CLEAR ADDRESS SILO (WO). AUTADR = 20 ;AUTO ADDRESS (R/W). CHNOPN = 10 ;CHANNEL OPEN (RO). NOWMST = 4 ;NOW MASTER (R/W). SEC = 2 ;SECONDARY MASTER (R/W). MASTER = 1 ;MASTER (R/W). ;+ ; PAD TRANSMITTER ID ;- PAD = 31. ;PAD TRANSMITTER ID ;+ ; DEVICE DISPATCH TABLE ;- DDT$ LT,L$$T11,,CHK ;GENERATE DISPATCH TABLE ;+ ; LOCAL IMPURE DATA TABLES ;- PRVAL: .BLKW L$$T11 ;PREVIOUS VALUE ASCNT: .BLKW L$$T11 ;ADDRESS SILO COUNTER LFVAL: .BLKW L$$T11 ;VALUES LEFT IN USER BUFFER FRVAL: .BLKW L$$T11 ;FIRST VALUE IN SILO ;+ ; LTCHK - PCL TRANSMITTER DRIVER PARAMETER CHECKING ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUEST ; IS RECEIVED FOR THE PARALLEL COMMUNICATIONS LINK TRANSMITTER. SOME ; PCL TRANSMITTER REQUESTS CONTAIN INFORMATION THAT MUST BE CHECKED IN ; THE CONTEXT OF THE ISSUING TASK; THEREFORE, THE I/O REQUEST IS NOT ; QUEUED BEFORE CALLING THE DRIVER. ; ; INPUTS: ; ; R1 = ADDRESS OF THE I/O PACKET ; R4 = ADDRESS OF THE STATUS CONTROL BLOCK ; R5 = ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED ; ; OUTPUTS: ; ; IF THE QIO FUNCTION IS IO.STC THEN NO PRIOR ADDRESS CHECKING HAS ; BEEN PERFORMED BY THE SYSTEM BECAUSE IO.STC IS CLASSED AS A CONTROL ; FUNCTION. IT IS THEREFORE NECESSARY TO FIRST MOVE ALL THE ; PARAMETERS SO THAT THE ADDRESS DOUBLEWORD FOR THE DATA BUFFER MAY ; BE MOVED TO I.PRM AND I.PRM+2 AFTER IS HAS BEEN ADDRESS CHECKED ; AND RELOCATED. IF THE LENGTH OF THE DATA BUFFER IS ZERO, THE ; ADDRESS CHECK WILL NOT TAKE PLACE AND THE ZERO LENGTH BUFFER WILL ; BE CONSIDERED VALID. ; ; IF THE QIO FUNCTION IS IO.STC OR IO.ATX THEN THE RETURN BUFFER ; ADDRESS IS CHECKED TO DETERMINE WHETHER IT LIES WITHIN THE ; ISSUING TASK'S ADDRESS SPACE. IF IT DOES THEN THE RETURN BUFFER ; ADDRESS IS RELOCATED AND STORED IN THE I/O PACKET. IF IT IS NOT ; A VALID ADDRESS THEN AN ILLEGAL BUFFER STATUS IS RETURNED AS THE ; FINAL I/O STATUS OF THE REQUEST. ; ; FOR ALL FUNCTION CODES, THE I/O PACKET IS INSERTED IN THE ; CONTROLLER QUEUE AND THE DEVICE INITIATOR IS ENTERED TO START ; THE CONTROLLER. ;- LTCHK: CMP #IO.ATX,I.FCN(R1) ;IS FUNCTION CODE = 'ATX'? BEQ 30$ ;IE EQ YES CMP #IO.STC,I.FCN(R1) ;IS FUNCTION CODE = 'STC'? BNE 60$ ;IF NE NO ; ; 'STC' FUNCTION - MOVE ALL PARAMETERS TO MAKE WAY FOR DATA BUFFER ; ADDRESS DOUBLEWORD ; 10$: MOV R1,R3 ;SAVE ADDRESS OF THE I/O PACKET MOV I.PRM+12(R3),I.PRM+14(R3) ;MOVE RETURN BUFFER ADDRESS MOV I.PRM+10(R3),I.PRM+12(R3) ;MOVE EVENT FLAG NUMBER MOV I.PRM+6(R3),I.PRM+10(R3) ;MOVE MODE MOV I.PRM+4(R3),I.PRM+6(R3) ;MOVE STATUS MOV I.PRM+2(R3),I.PRM+4(R3) ;MOVE LENGTH OF BUFFER BEQ 30$ ;IF EQ LENGTH = 0 BLT 15$ ;IF LT INVALID BUFFER LENGTH ; ; SET UP REGISTERS FOR ADDRESS CHECK AND RELOCATION ; MOV I.PRM(R3),R0 ;DATA BUFFER ADDRESS ==> R0 MOV I.PRM+2(R3),R1 ;LENGTH ==> REG 1 CALL $ACHCK ;CHECK THE LENGTH BCS 15$ ;IF CS, ERROR MOV W.BATT(R2),R2 ;PICK UP ATTACHMENT DESC. ADDR. INCB A.IOC(R2) ;LOCK REGION MOV R2,I.AADA(R3) ;SAVE PTR IN PKT FOR $IODONE BR 20$ ;CONTINUE ; ; INVALID BUFFER ; 15$: MOV #IE.SPC&377,R0 ;SET ILLEGAL BUFFER STATUS CALLR $IOFIN ;CALL FINISH I/O OPERATION AND EXIT ; ; RELOCATE THE DATA BUFFER ADDRESS ; 20$: CALL $RELOC ;GO RELOCATE THE DATA BUFFER ADDRESS MOV R1,I.PRM(R3) ;SET RELOCATION BIAS MOV R2,I.PRM+2(R3) ;SET 16-BIT ADDRESS BR 40$ ;GO CHECK RETURN BUFFER ADDRESS ; ; 'STC' OR 'ATX' FUNCTION ; 30$: MOV R1,R3 ;SAVE I/O PACKET 40$: MOV I.PRM+14(R3),R0 ;GET VIRTUAL ADDRESS OF RETURN BUFFER MOV #14.,R1 ;SET LENGTH OF RETURN BUFFER TO 7 WORDS CALL $ACHCK ;CHECK THE ADDRESS BCS 15$ ;IF CS BAD MOV W.BATT(R2),R2 ;PICK UP ATTACHMENT DESC. ADDR. INCB A.IOC(R2) ;LOCK REGION MOV R2,I.AADA+2(R3) ;SAVE PTR IN PKT FOR $IODONE ; ; RELOCATE THE RETURN BUFFER ADDRESS ; CALL $RELOC ;RELOCATE USER BUFFER MOV R1,I.PRM+14(R3) ;SET RELOCATION BIAS OF RETURN BUFFER MOV R2,I.PRM+16(R3) ;SET 16-BIT ADDRESS OF RETURN BUFFER MOV R3,R1 ;COPY I/O PACKET ADDRESS ; ; INSERT THE I/O PACKET IN THE QUEUE ; 60$: MOV R4,R0 ;SET R0 = I/O QUEUE LISTHEAD CALL $QINSP ;GO INSERT PACKET IN QUEUE ; ; GET THE QUEUED I/O PACKET ; LTINI: GTPKT$ LT,L$$T11,,,T ;GET I/O PACKET MACRO ; ; ANALYZE THE CONTENTS OF THE I/O PACKET ; ; R1 = I/O PACKET ; R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB ; R3 = CONTROLLER INDEX ; R4 = STATUS CONTROL BLOCK ; R5 = UNIT CONTROL BLOCK ; ; I/O REQUEST PACKET FORMAT ; ; WD.00 = I/O QUEUE THREAD WORD ; WD.01 = REQUEST PRIORITY, EVENT FLAG NUMBER ; WD.02 = TSB ADDRESS OF REQUESTER TASK ; WD.03 = POINTER TO 2ND LUN WORD IN REQUESTER TASK HEADER ; WD.04 = CONTENTS OF 1ST LUN WORD IN REQUESTER TASK HEADER ; WD.05 = I/O FUNCTION CODE ; WD.06 = VIRTUAL ADDRESS OF I/O STATUS BLOCK ; WD.07 = RELOCATION BIAS OF I/O STATUS BLOCK ; WD.10 = I/O STATUS BLOCK ADDRESS ; WD.11 = VIRTUAL ADDRESS OF AST SERVICE ROUTINE ; WD.12 = RELOCATION BIAS OF DATA BUFFER ; WD.13 = 16-BIT ADDRESS OF DATA BUFFER ; WD.14 = LENGTH OF DATA BUFFER ; WD.15 = FLAG WORD OR STATE ; WD.16 = ID OR MODE ; WD.17 = NUMBER OF RETRIES OR EVENT FLAG NUMBER ; WD.20 = RELOCATION BIAS OF RETURN BUFFER ; WD.21 = 16-BIT ADDRESS OF RETURN BUFFER ; TST U.EFN(R5) ;WAS EFN FOR 'NOWMST' SPECIFIED? BEQ 5$ ;IF EQ NO MOV S.CSR(R4),R0 ;YES, RETREIVE CSR ADDRESS BIS #IE,(R0) ;ENABLE INTERRUPTS 5$: MOV I.TCB(R1),R0 ;GET REQUESTER TCB ADDRESS. BITB #T2.ABO,T.ST2(R0) ;IS TASK BEING ABORTED? BEQ 10$ ;IF EQ NO CALLR IEVER ;YES, REJECT REQUEST ; ; DISPATCH PACKET FOR PROCESSING ACCORDING TO FUNCTION CODE ; 10$: CMP #IO.ATX,I.FCN(R1) ;IS IT 'ATX' FUNCTION? BEQ ATX ;IF EQ YES CMP #IO.SEC,I.FCN(R1) ;IS IT 'SEC' FUNCTION? BEQ IOSEC ;IF EQ YES CMP #IO.STC,I.FCN(R1) ;IS IT 'STC' FUNCTION? BEQ STC ;IF EQ YES CALLR IEIFC ;INVALID FUNCTION CODE ;+ ; PROCESS 'ATX' FUNCTION ; ; REQUIRED INPUTS: ; R1 = I/O PACKET ; R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB ; R3 = CONTROLLER INDEX ; R4 = STATUS CONTROL BLOCK ; R5 = UNIT CONTROL BLOCK ;- ATX: ;REF LABEL .IF DF M$$EXT CALL $STMAP ;SET UP UNIBUS MAP ADDRESS CALL $MPUBM ;MAP UNIBUS TO MEMORY MOV S.PKT(R4),R1 ;RESTORE REG 1 .ENDC CMPB I.PRM+11(R1),#DC/400 ;CPU ID > MAXIMUM? BHI LTBAD ;IF HI YES TSTB I.PRM+11(R1) ;CPU ID = 0? BEQ LTBAD ;IF EQ YES TSTB I.PRM+13(R1) ;RETRY COUNT > 255? BNE LTBAD ;IF NE YES MOVB I.PRM+12(R1),U.CW2(R5) ;SAVE RETRY COUNT BYTE. ; ; SET UP RETURN REGISTER BUFFER ADDRESS IN UCB ; MOV I.PRM+14(R1),U.BUF1(R5) ;RELOCATION BIAS ==> UCB MOV I.PRM+16(R1),U.BUF1+2(R5) ;16-BIT ADDRESS==> UCB RETRY: MOV S.CSR(R4),R0 ;GET DEVICE ADDRESS (TSR). MOV #BDINIT,(R0) ;BOARD INITIALIZE. MOV I.PRM+6(R1),TSDB(R0) ;MOVE FLAGS WORD TO DATA SILO. MOV U.BUF+2(R5),TSBA(R0) ;SET UP BUFFER ADDRESS. MOV U.CNT(R5),R2 ;GET BYTE COUNT NEG R2 ;NEGATE IT. MOV R2,TSBC(R0) ;PUT IT IN PCL REGISTER. MOVB I.PRM+11(R1),TCR+1(R0) ;SET CPU ID. BIS #RIB!TXNPR!SNDWD!IE!STTXM,U.BUF(R5) ;SET EXTENDED BIS U.BUF(R5),(R0) ;ADDR & GO BITS IN TCR. MOVB S.ITM(R4),S.CTM(R4) ;- SET TIME OUT RETURN ; LTBAD: CALLR IEBAD ;BAD PARAMETERS ;+ ; PROCESS 'SEC' FUNCTION ; ; REQUIRED INPUTS: ; R4 = STATUS CONTROL BLOCK ;- IOSEC: MOV S.CSR(R4),R0 ;GET DEVICE ADDRESS MOV TMMR(R0),R1 ;MOVE SECOND WORD FOR IOSB TO R1 MOV #IS.SUC&377,R0 ;GET SUCCESS STATUS CODE CALL $IODON ;GO EXIT THIS REQUEST BR LTINI ;GO LOOK FOR MORE WORK ;+ ; PROCESS 'STC' FUNCTION ; ; REQUIRED INPUTS: ; R1 = I/O PACKET ; R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB ; R3 = CONTROLLER INDEX ; R4 = STATUS CONTROL BLOCK ; R5 = UNIT CONTROL BLOCK ;- STC: MOV I.TCB(R1),R0 ;GET TASK'S TCB ADDRESS BIT #T3.PRV,T.ST3(R0) ;IS THE TASK PRIVLEGED? BEQ 35$ ;IF EQ NO TST I.PRM+6(R1) ;'STATE' SPECIFIED? BEQ 10$ ;IF EQ NO CMP #SS.MAS,I.PRM+6(R1) ;IS IT 'MASTER'? BEQ 10$ ;IF EQ YES ;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED ; CMP #SS.SEC,I.PRM+6(R1) ;IS IT 'SECONDARY'? ; BEQ 10$ ;IF EQ YES CMP #SS.NEU,I.PRM+6(R1) ;IS IT 'NEUTRAL'? BNE LTBAD ;IF NE NO, BAD PARAMETERS ; ; VALIDATE THE 'MODE' PARAMETER ; 10$: TST I.PRM+10(R1) ;'MODE' SPECIFIED? BEQ 20$ ;IF EQ NO CMP #MS.AUT,I.PRM+10(R1) ;IS 'AUTO' SPECIFIED? BEQ 20$ ;IF EQ YES CMP #MS.ADS,I.PRM+10(R1) ;IS 'ADDRESS SILO' SPECIFIED? BNE LTBAD ;IF NE NO, BAD PARAMETERS ; ;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED ; VALIDATE THE EVENT FLAG NUMBER ; 20$: BR 40$ ; TST I.PRM+12(R1) ;EVENT FLAG > 0? ; BLE 30$ ;IF LE NO ; CMP #96.,I.PRM+12(R1) ;IS IT > 96? ; BGT 40$ ;IF GT NO 30$: CALLR IEIEF ;INVALID EVENT FLAG 35$: CALLR IEPRI ;PRIVLEGE VIOLATION ; ; VALIDATE THE SIZE AND CONTENTS OF THE DATA BUFFER ; 40$: TST I.PRM+4(R1) ;IS SIZE OF BUFFER > OR = 0? BLT 54$ ;IF LT NO BEQ 60$ ;IF EQ SIZE=0 ; ; INITIALIZE VALUES FOR LOOPING THROUGH BUFFER ; MOV #50.,ASCNT(R3) ;SAVE MAX NUMBER OF VALUES ALLOWED CMP I.PRM+4(R1),ASCNT(R3) ;IS # OF VALUES > MAXIMUM? BGT 54$ ;IF GT YES CLR PRVAL(R3) ;INITIALIZE PREVIOUS VALUE TO ZERO MOV I.PRM+4(R1),LFVAL(R3) ;GET # OF VALUES MOV I.PRM(R1),U.BUF(R5) ;GET RELOCATION BIAS MOV I.PRM+2(R1),U.BUF+2(R5) ;GET VITUAL ADDRESS ; ; CHECK ALL VALUES IN THE BUFFER FOR WITHIN VALID RANGE ; ; PRVAL(R3) = PREVIOUS VALUE ; ASCNT(R3) = # VALUES STILL POSSIBLE TO ADD TO SILO ; LFVAL(R3) = # VALUES STILL IN USER BUFFER ; 50$: CALL $GTBYT ;RETRIEVE NEXT BYTE ON THE STACK TSTB (SP) ;IS VALUE > 0? BEQ 51$ ;IF EQ NO CMPB (SP),#DC/400 ;IS VALUE > MAXIMUM? BLE 52$ ;IF LE NO 51$: MOVB (SP)+,PRVAL(R3) ;CLEAN UP THE STACK BR 54$ ;INVALID DATA BUFFER ; ; CHECK FOR PAD VALUE NEEDED ; 52$: CMPB (SP),PRVAL(R3) ;IS IT = LAST VALUE? BNE 53$ ;IF NE NO DEC ASCNT(R3) ;DECREMENT MAXIMUM VALUES ALLOWED ; ; DECREMENT COUNTERS AND SAVE PREVIOUS VALUE ; 53$: MOVB (SP)+,PRVAL(R3) ;SAVE THIS VALUE AS PREVIOUS DEC ASCNT(R3) ;DECREMENT MAXIMUM VALUES ALLOWED BGE 55$ ;IF GE STILL WITHIN LIMITS 54$: CALLR IESPC ;ILLEGAL BUFFER FORMAT ; ; DECREMENT NUMBER OF BYTES STILL IN USER BUFFER AND GO GET NEXT BYTE ; 55$: DEC LFVAL(R3) ;DECREMENT # BYTES YET TO CHECK BGT 50$ ;IF GT GET NEXT ; ; ALL PARAMETERS ARE VALID - PROCESS THE REQUEST ; 60$: BR 70$ ; TST U.TCB(R5) ;HAS A TASK REQUESTED AN EVENT FLAG? ; BEQ 62$ ;IF EQ NO ; CMP I.TCB(R1),U.TCB(R5) ;IS THIS THE SAME REQUESTOR? ; BEQ 61$ ;IF EQ YES ; CALLR IEFLG ;EVENT FLAG ALREADY SPECIFIED ; ; DECREMENT I/O COUNT FOR PREVIOUS EVENT FLAG ; ;61$: MOV U.TCB(R5),R0 ;GET PREVIOUS REQUESTOR ; DECB T.IOC(R0) ;DECREMENT REQUESTOR'S I/O COUNT ;; ; SET UP TCB & EVENT FLAG ; ;62$: MOV I.PRM+12(R1),U.EFN(R5) ;SET UP EVENT FLAG NUMBER ; BNE 63$ ;IF NE NON-ZERO EVENT FLAG ; CLR U.TCB(R5) ;ZERO REQUESTORS TCB ; BR 70$ ;GO PROCESS NEXT PARAMETER ; ; EVENT FLAG HAS BEEN SPECIFIED, SETUP TCB IN UCB AND INCREMENT ; I/O COUNT. ; ;63$: MOV I.TCB(R1),R0 ;SAVE REQUESTORS TCB ; MOV R0,U.TCB(R5) ; ; INCB T.IOC(R0) ;LOCK DOWN TASK ; ; INITIALIZE BASE REGISTER ADDRESS ; 70$: MOV S.CSR(R4),R0 ;TSR ==> REG 0 TST I.PRM+6(R1) ;WAS A 'STATE' SPECIFIED? BEQ 80$ ;IF EQ NO CMP #SS.MAS,I.PRM+6(R1) ;IS MASTER STATE DESIRED? BNE 71$ ;IF NE NO MOV #MASTER,ASCNT(R3) ;SET MASK FOR MASTER BR 73$ ;GO CHANGE TMMR 71$: ; CMP #SS.SEC,I.PRM+6(R1) ;IS SECONDARY STATE DESIRED? ; BNE 72$ ;IF NE NO ; MOV #SEC,ASCNT(R3) ;SET MASK FOR SECONDARY ; BR 73$ ;GO CHANGE TMMR 72$: CLR ASCNT(R3) ;SET NEUTRAL MASK 73$: MOVB TMMR+1(R0),PRVAL(R3);GET HIGH ORDER BYTE OF TMMR BICB #MASTER!SEC,PRVAL(R3) ;CLEAR PREVIOUS STATE BISB ASCNT(R3),PRVAL(R3) ;SET NEW STATE MOVB PRVAL(R3),TMMR+1(R0) ;STORE NEW HIGH ORDER BYTE MOVB TMMR+1(R0),PRVAL(R3) ;GET NEW HIGH ORDER BYTE AGAIN BICB #374,PRVAL(R3) ;CLEAR ALL BUT DESIRED BITS CMPB ASCNT(R3),PRVAL(R3) ;IS ACTUAL = DESIRED? BEQ 80$ ;IF EQ YES ; ; NOT DESIRED STATE - CHECK FOR VALID EXCEPTION (SECONDARY==>MASTER) ; BITB #MASTER,PRVAL(R3) ;IS IT NOW MASTER? BNE 80$ ;IF NE YES CALLR IEVER ;HARDWARE REJECTED STATE ; ; SET UP ADDRESS SILO ; 80$: TST I.PRM+4(R1) ;IS LENGTH OF DATA BUFFER = 0? BEQ 90$ ;IF EQ YES MOVB TMMR+1(R0),PRVAL(R3);RETRIEVE HIGH ORDER BYTE OF TMMR BISB #CLRADR!AUTADR,PRVAL(R3) ;CLEAR SILO AND SET AUTO ADRS MOVB PRVAL(R3),TMMR+1(R0) ;STORE NEW HIGH ORDER BYTE ; ; REINITIALIZE UCB FOR THE DATA TRANSFER ; MOV I.PRM(R1),U.BUF(R5) ;RELOCATION BIAS ==> UCB MOV I.PRM+2(R1),U.BUF+2(R5) ;16-BIT ADDRESS ==> UCB CLR ASCNT(R3) ;ZERO ADDRESS SILO ENTRY COUNTER CLR PRVAL(R3) ;SET PREVIOUS VALUE TO ZERO MOV I.PRM+4(R1),LFVAL(R3) ;INITIALIZE DATA BUFFER COUNTER ; ; MOVE EACH BYTE OF THE DATA BUFFER TO THE ADDRESS SILO ; ; PRVAL(R3) = PREVIOUS VALUE ; ASCNT(R3) = ADDRESS SILO COUNTER ; LFVAL(R3) = # BYTES STILL IN DATA BUFFER ; FRVAL(R3) = FIRST VALUE IN SILO ; 81$: CALL $GTBYT ;RETRIEVE A BYTE FROM USER BUFFER CMPB (SP),PRVAL(R3) ;IS IT = PREVIOUS? BNE 82$ ;IF NE NO MOVB #PAD,TMMR(R0) ;INSERT A PAD VALUE INC ASCNT(R3) ;INCREMENT ADDRESS SILO ENTRY COUNTER 82$: MOVB (SP),PRVAL(R3) ;SAVE THIS VALUE AS PREVIOUS TST ASCNT(R3) ;IS THIS FIRST BYTE? BGT 83$ ;IF GT NO MOVB (SP),FRVAL(R3) ;SAVE FIRST VALUE 83$: MOVB (SP)+,TMMR(R0) ;INSERT THE USER VALUE IN SILO INC ASCNT(R3) ;INCREMENT ADDRESS SILO COUNTER DEC LFVAL(R3) ;DECREMENT # BYTES YET TO MOVE BGT 81$ ;IF GT GET NEXT BYTE CMP #20.,ASCNT(R3) ;HAVE AT LEAST 20 VALUES BEEN INSERTED? BLE 84$ ;IF LE YES ; ; LESS THAN THE MINIMUM NUMBER OF VALUES HAVE BEEN MOVED - REPEAT THE ; PATTERN AGAIN ; MOV I.PRM(R1),U.BUF(R5) ;RELOCATION BIAS ==> UCB MOV I.PRM+2(R1),U.BUF+2(R5) ;16-BIT ADDRESS ==> UCB MOV I.PRM+4(R1),LFVAL(R3) ;SET UP # BYTES TO MOVE BR 81$ ;GO MOVE THE VALUES ; ; ALL BYTES MOVED - CHECK FOR FIRST = LAST ; 84$: CMPB PRVAL(R3),FRVAL(R3) ;IS FIRST = LAST? BNE 90$ ;IF NE NO MOVB #PAD,TMMR(R0) ;MOVE A PAD VALUE TO SILO 90$: TST I.PRM+10(R1) ;WAS A MODE SPECIFIED? BEQ 100$ ;IF EQ NO MOVB TMMR+1(R0),PRVAL(R3);RETRIEVE HIGH BYTE OF TMMR CMP #MS.AUT,I.PRM+10(R1) ;AUTO ADDRESS SPECIFIED? BNE 91$ ;IF NE NO BISB #AUTADR,PRVAL(R3) ;SET AUTO ADDRESS BR 92$ ;GO RESTORE TMMR+1 ; ; ADDRESS SILO REQUESTED ; 91$: BICB #AUTADR,PRVAL(R3) ;CLEAR AUTO ADDRESS (IMPLIES SILO) 92$: MOVB PRVAL(R3),TMMR+1(R0);RESTORE HIGH BYTE OF TMMR 100$: MOV I.PRM+14(R1),U.BUF1(R5) ;RELOCATION BIAS ==> UCB MOV I.PRM+16(R1),U.BUF1+2(R5) ;16-BIT ADDRESS ==> UCB BEQ 110$ ;IF EQ NO CALL REGRET ;GO RETURN REGISTERS 110$: CALLR ISSUC ;INDICATE SUCCESS AND EXIT ;+ ; REGRET -- SERVICE ROUTINE TO RETURN THE CONTENTS OF THE TRANSMITTER ; SIDE REGISTERS TO THE USER BUFFER WHOSE ADDRESS IS SPECIFIED IN ; U.BUF1 AND U.BUF1+2 IN THE UCB. THE CONTROL REGISTER ADDRESS IS ; CONTAINED IN R0. U.BUF AND U.BUF+2 ARE PRESERVED ACROSS CALL. ;- REGRET: TST U.BUF1(R5) ;RELOCATION BIAS = 0? BNE 10$ ;IF NE NO TST U.BUF1+2(R5) ;IS 16 BIT ADDRESS = 0? BEQ 20$ ;IF EQ YES 10$: MOV U.BUF(R5),-(SP) ;SAVE U.BUF MOV U.BUF+2(R5),-(SP) ;SAVE U.BUF+2 MOV U.BUF1(R5),U.BUF(R5) ;GET RELOCATION BIAS MOV U.BUF1+2(R5),U.BUF+2(R5) ;GET VIRTUAL ADDRESS .REPT 7 MOV (R0)+,-(SP) ;GET WORD TO STORE CALL $PTWRD ;PUT WORD INTO BUFFER .ENDR MOV (SP)+,U.BUF+2(R5) ;RESTORE U.BUF+2 MOV (SP)+,U.BUF(R5) ;RESTORE U.BUF 20$: RETURN ; ;+ ; INTERRUPT SERVICE ROUTINE ;- .ENABL LSB $LTINT:: INTSV$ LT,PR5,L$$T11 ;;;EXECUTE INTERRUPT SAVE CODE MOV U.SCB(R5),R4 ;;;GET SCB ADDRESS. MOV S.CSR(R4),R4 ;;;GET TCR ADDRESS. BIC #IE,(R4) ;;;DISABLE INTERRUPTS. BITB #US.BSY,U.STS(R5) ;;;IS UNIT BUSY? BEQ 10$ ;;;IF EQ NO TST TSR(R4) ;;;ERROR CONDITION? BPL 5$ ;;;IF PL, NO ERROR CALL $FORK ;;;CREATE A SYSTEM PROCESS JMP ERROR ;GO HANDLE ERRORS 5$: TSTB TSR(R4) ;;;SUCTXF? BMI 30$ ;;;IF MI YES BIT #SORE,TSR(R4) ;;;HAVE WE A SOFTWARE REJECT ? BNE 20$ ;;;IF NE YES 10$: ;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED ; BITB #NOWMST,TMMR+1(R4) ;;;HAVE WE BECOME MASTER? ; BNE 50$ ;;;IF NE YES BIS #BDINIT,(R4) ;;;TX INIT JUST IN CASE RETURN ;;;RETURN FOR MORE ; ; PROCESS SOFTWARE REJECT ; 20$: BIC #SORE,(R4) ;;;CLEAR THE INTERRUPTING BIT CALL $FORK ;;;CREATE FORK PROCESS MOV R4,R0 ;COPY CSR ADDRESS CALL REGRET ;RESTORE REGISTERS CALLR IEREJ ;REJECT REQUEST 30$: BIC #SUCTXF,TSR(R4) ;;;CLEAR THE INTERRUPTING BIT CALL $FORK ;;;CREATE FORK PROCESS MOV R4,R0 ;COPY CSR ADDRESS CALL REGRET ;RESTORE REGISTERS MOV #IS.SUC&377,R0 ;GET SUCCESS STATUS CODE BIT #SORE,TSR(R4) ;WAS TRANSMISSION TRUNCATED? BEQ 40$ ;IF EQ NO BIC #SORE,TSR(R4) ;CLEAR THE SORE BIP ALSO INC R0 ;BUMP STATUS TO IS.TNR 40$: MOV U.CNT(R5),R1 ;GET # OF BYTES TRANSFERED CALL $IODON ;FINISH I/O JMP LTINI ;TRY FOR MORE ;EVENT FLAG FEATURE AND SECONDARY STATE CAPABILITY HAVE BEEN REMOVED ; ; NOWMST INTERRUPT - SET EVENT FLAG ; ;50$: CALL $FORK ;;;CREATE FORK PROCESS ; MOV U.SCB(R5),R3 ;RETREIVE SCB ADDRESS ; MOVB S.CON(R3),R3 ;RETREIVE CONTROLLER INDEX ; MOVB TMMR+1(R4),PRVAL(R3) ;RETRIEVE TMMR+1 ; BICB #NOWMST,PRVAL(R3) ;CLEAR 'NOWMST' BIT ; MOVB PRVAL(R3),TMMR+1(R4) ;RESTORE TMMR+1 ; MOV R5,PRVAL(R3) ;SAVE REG 5 ; MOV U.EFN(R5),R0 ;EVENT FLAG # ==> R0 ; MOV U.TCB(R5),R5 ;REQUESTORS TCB ==> R5 ; BEQ 51$ ;IF EQ NONE ; CALL $CEFI ;GO CONSTRUCT EVENT FLAG MASK ; BCS 51$ ;IF CS NO EVENT SPECIFIED ; BIS R0,(R1) ;SET EVENT FLAG ; CALL $DRDSE ;DECLARE SIGNIFICANT EVENT ; DECB T.IOC(R5) ;UNLOCK TCB, EFN IS GOING AWAY ;51$: MOV PRVAL(R3),R5 ;RESTORE REG 5 ; CLR U.EFN(R5) ; ; CLR U.TCB(R5) ; ; RETURN ;RETURN TO INTERRUPTED PROGRAM .DSABL LSB ;+ ; WE HAVE AN ERROR CONDITION. WE WILL DETERMINE THE CAUSE OF THE ; ERROR AND TAKE THE APPROPRIATE ACTION AS FOLLOWS: ; ; OVERRUN = IE.BBE ; TIMEOUT = IE.DNR ; MASTER DOWN = IE.DNR ; XMIT ERROR ; RSP B = 00 = IE.DNR ; RSP B = 01,10,11 = IE.BBE ; MEM OVERFLOW = INCREMENT A16-17, CLEAR ERROR, ENABLE IE, ; SET STTXM ; NEM = SET BDINIT, IE.SPC ;- ERROR: MOV R4,R0 ;COPY CSR ADDRESS CALL REGRET ;RESTORE REGISTERS MOV TSR(R4),R1 ;GET CONTENTS OF TSR. BIT #OVERUN,R1 ;CHECK FOR OVER RUN. BNE 110$ ;IF NE OVERRUN BIT #MSTDWN,R1 ;CHECK FOR MASTER DOWN. BNE 130$ ;IF NE MASTER DOWN BIT #TIMOUT,R1 ;CHECK FOR TIME OUT. BNE 120$ ;IF NE TIMEOUT BIT #TXMERR,R1 ;CHECK FOR TRANSMISSION ERROR. BNE 140$ ;IF NE TRANSMISSION ERROR BIT #MEMOFL!NEXLOC,R1 ;OVERFLOW OR NEM? BNE 170$ ;IF NE YES BIS #BDINIT,(R4) ;INIT THE BOARD AGAIN RETURN ; ;+ ; PROCESS OVERRUN CONDITION ;- 110$: BIC #OVERUN,TSR(R4) ;CLEAR THE INTERRUPTING BIT CALLR IEBBE ;TRANSMISSION ERROR ;+ ; PROCESS TIMEOUT ;- 120$: BIC #TIMOUT,TSR(R4) ;CLEAR THE INTERRUPTING BIT CALLR IEDNR ;DEVICE NOT READY ;+ ; PROCESS MASTER DOWN. ;- 130$: BIC #MSTDWN,TSR(R4) ;CLEAR THE INTERRUPTING BIT MOV #IE.DNR&377,R0 ;GET DEVICE NOT READY CODE BR 150$ ;GO TRY FOR A RETRY ;+ ; PROCESS TRANSMISSION ERROR. ;- 140$: BIC #TXMERR,TSR(R4) ;CLEAR INT BIT BIT #RSPB1!RSPB0,R1 ;IF RSPB IS 00 BEQ 120$ ;IF EQ TREAT AS TIMEOUT MOV #IE.BBE&377,R0 ;GET TRANSMIT ERROR STATUS CODE 150$: MOV U.SCB(R5),R4 ;GET SCB ADDRESS MOV S.PKT(R4),R1 ;LOAD ADDRESS OF I/O PACKET DECB U.CW2(R5) ;DECREMENT RETRY COUNT. BGE 160$ ;IF GE RETRY CALLR IODON ;FINISH UP 160$: JMP RETRY ;GO TRY AGAIN ;+ ; PROCESS MEMORY OVERFLOW & NONEXISTENT LOCATION. ;- 170$: BIS #BDINIT,(R4) ;INITIALIZE BOARD. CALLR IESPC ;RETURN NON-EXISTANT ERROR ;+ ; CANCEL I/O OPERATION ; ; INPUTS: ; ; R0 = I/O PACKET ADDRESS ; R1 = TCB ADDRESS ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ;- LTCAN: MTPS #0 ;;;LOWER PRIORITY CMP R1,U.TCB(R5) ;DID THIS TASK ASK FOR AN EVENT FLAG? BNE 10$ ;IF NE NO DECB T.IOC(R1) ;UNLOCK TCB, EFN IS GOING AWAY CLR U.EFN(R5) ;CLEAR EVENT FLAG NUMBER CLR U.TCB(R5) ;CLEAR REQUESTORS TCB 10$: TSTB S.STS(R4) ;IS UNIT BUSY? BEQ LTPWF ;IF EQ THEN YES CMP R1,I.TCB(R0) ;IS CANCEL REQUEST FOR THE CURRENT TASK? BNE LTPWF ;IF NE, NO SIMPLY RETURN MOV #IE.ABO&377,R0 ;LOAD ABORT STATUS CODE BR ABORT ;ABORT THIS OPERATION LTPWF: RETURN ;NO, JUST RETURN ;+ ; TIMEOUT SERVICE ;- LTOUT: MOV #IE.DNR&377,R0 ;LOAD NOT READY STATUS CODE. ABORT: MOV S.CSR(R4),R2 ;GET TSR ADDRESS. BIS #BDINIT,(R2) ;INITIALIZE PCL TRANSMITTER. BR IODON ;FINISH I/O ;+ ; PROCESS ERROR CONDITIONS AND CALL I/O DONE ;- IEBAD: MOV #IE.BAD&377,R0 ;BAD PARAMETERS BR IODON ; IEBBE: MOV #IE.BBE&377,R0 ;TRANSMISSION ERROR BR IODON ; IEDNR: MOV #IE.DNR&377,R0 ;DEVICE NOT READY BR IODON ; IEFLG: MOV #IE.FLG&377,R0 ;EVENT FLAG ALREADY SPECIFIED BR IODON ; IEIEF: MOV #IE.IEF&377,R0 ;INVALID EVENT FLAG BR IODON ; IEIFC: MOV #IE.IFC&377,R0 ;INVALID FUNCTION CODE BR IODON ; IEPRI: MOV #IE.PRI&377,R0 ;PRIVLEGE VIOLATION BR IODON ; IEREJ: MOV #IE.REJ&377,R0 ;TRANSFER REJECTED BR IODON ; IESPC: MOV #IE.SPC&377,R0 ;INVALID PARAMETERS BR IODON ; IEVER: MOV #IE.VER&377,R0 ;PARITY ERROR BR IODON ; ISSUC: MOV #IS.SUC&377,R0 ;SUCCESSFUL OPERATION IODON: CALL $IOALT ;FINISH I/O JMP LTINI ;TRY FOR MORE .END